package barinadroid.game;

import org.andengine.engine.camera.Camera;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.LoopEntityModifier;
import org.andengine.entity.modifier.MoveXModifier;
import org.andengine.entity.modifier.RotationModifier;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.util.color.Color;
import android.util.Log;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;

public class Ship extends GameEntity
{
	public static Ship instance;

	public static Ship getSharedInstance()
	{
		if(instance == null)
			instance = new Ship();
		return instance;
	}

	Camera mCamera;
	private boolean moveable, isTryingToFire;
	// private int shieldAmount;
	private Vector2 velocity, speed;
	private Rectangle shieldSprite, cannon;
	private CoolDown shootCoolDown;

	private Ship()
	{
		// this.sprite = new Sprite(0, 0,
		// GameActivity.getSharedInstance().shipRegion,
		// GameActivity.getSharedInstance().getVertexBufferObjectManager());
		this.sprite = new Rectangle(0, 0, 100, 100, GameActivity.getSharedInstance().getVertexBufferObjectManager());
		this.sprite.setRotationCenter(sprite.getWidth() * .5f, sprite.getHeight() * .5f);
		this.sprite.setColor(Color.WHITE);
		this.shieldSprite = new Rectangle(-10, -10, 120, 120, GameActivity.getSharedInstance().getVertexBufferObjectManager());
		this.shieldSprite.setColor(1f, 1f, 1f, .5f);
		this.shieldSprite.registerEntityModifier(new LoopEntityModifier(new RotationModifier(4f, 0, 360)));
		cannon = new Rectangle(sprite.getWidth() - 5, sprite.getHeight() / 2 - 5, 10, 10, GameActivity.getSharedInstance().getVertexBufferObjectManager());
		cannon.setColor(.5f, .5f, .5f, .9f);
		this.sprite.attachChild(shieldSprite);
		this.sprite.attachChild(cannon);
		this.mCamera = GameActivity.getSharedInstance().camera;
		this.sprite.setPosition(mCamera.getWidth() / 2 - sprite.getWidth() / 2, mCamera.getHeight() - sprite.getHeight() - 10);
		setMoveable(true);
		this.velocity = new Vector2(15f, 15f);
		this.speed = new Vector2(1f, 1f);
		this.shootCoolDown = new CoolDown(250f);
	}

	// resets the ship to the middle of the screen
	public void restart()
	{
		setMoveable(false);
		stopFire();
		Camera mCamera = GameActivity.getSharedInstance().camera;
		MoveXModifier mod = new MoveXModifier(0.2f, sprite.getX(), mCamera.getWidth() / 2 - sprite.getWidth() / 2)
		{
			@Override
			protected void onModifierFinished(IEntity pItem)
			{
				super.onModifierFinished(pItem);
				setMoveable(true);
			}
		};
		sprite.registerEntityModifier(mod);
	}

	/***
	 * Will try to shoot.
	 * 
	 * @return The {@link Bullet} fired. <code>null</code> if wasn't succeed.
	 */
	public Bullet Shoot()
	{
		if(this.isTryToFire() && !this.shootCoolDown.Start())
			return BulletFactory.getSharedInstance().Shoot(this);
		return null;
	}

	public void normalizeShipsBodyVelocity(float pSecondsElapsed)
	{
		Vector2 velocity = body.getLinearVelocity().cpy();
		final float value = 25f * pSecondsElapsed;
		if(velocity.x != 0.0f)
		{
			if(velocity.x > 0.0f)
			{
				if((velocity.x -= value) < 0.0f)
					velocity.x = 0.0f;
			}
			else
			{
				if((velocity.x += value) > 0.0f)
					velocity.x = 0.0f;
			}
		}
		if(velocity.y != 0.0f)
		{
			if(velocity.y > 0.0f)
			{
				if((velocity.y -= value) < 0.0f)
					velocity.y = 0.0f;
			}
			else
			{
				if((velocity.y += value) > 0.0f)
					velocity.y = 0.0f;
			}
		}
		body.setLinearVelocity(velocity);
	}

	public void setVelocity(float axisX, float axisY)
	{
		if(isMoveable())
			if(axisX != 0 || axisY != 0)
			{
				final float velX = axisX == 0 ? body.getLinearVelocity().x : (this.velocity.x * this.speed.x) * axisX, velY = axisY == 0 ? body.getLinearVelocity().y
						: (this.velocity.y * this.speed.y) * axisY;
				body.setLinearVelocity(velX, velY);
			}
	}

	// /***
	// * @Deprecated Ships body cannot set within super abstract method
	// 'setBody'.
	// * it needs to receive a physicsWorld.. therefore use
	// * 'setBody(PhysicsWorld, FixtureDef)' instead.
	// * @see #setBody(PhysicsWorld, FixtureDef)
	// */
	// @Deprecated
	// @Override
	// protected void setBody(FixtureDef def)
	// {
	// Log.e("Ship",
	// "Ships body cannot set within super abstract method 'setBody'. it needs to receive a physicsWorld.. therefore use 'setBody(PhysicsWorld, FixtureDef)' instead.");
	// }
	/***
	 * @Deprecated Ships body cannot set within super abstract method 'setBody'.
	 *             it needs to receive a physicsWorld.. therefore use
	 *             'setBody(PhysicsWorld, EntityIdentity)' instead.
	 * @see #setBody(PhysicsWorld, EntityIdentity)
	 */
	@Deprecated
	@Override
	void setBody(EntityIdentity identity)
	{
		Log.e("Ship",
				"Ships body cannot set within super abstract method 'setBody'. it needs to receive a physicsWorld.. therefore use 'setBody(PhysicsWorld, FixtureDef)' instead.");
	}

	public void setBody(PhysicsWorld physicsWorld, EntityIdentity identity)
	{
		//this.body = PhysicsFactory.createBoxBody(physicsWorld, getSprite(), BodyType.DynamicBody, identity.getFixtureDef());
		

		float a = getSprite().getWidthScaled() * 0.5f / 32.0f;
		float b = getSprite().getHeightScaled() * 0.5f / 32.0f;
		Vector2[] v =
		{new Vector2(-a, -b), new Vector2(a, -b), new Vector2(a, b), new Vector2(-a, b)};
		this.body = PhysicsFactory.createPolygonBody(physicsWorld, getSprite(), v, BodyType.DynamicBody, identity.getFixtureDef());
		
		
		this.body.setUserData(this);
		setEntityIdentity(identity);
	}

	public boolean isMoveable()
	{
		return moveable;
	}

	public void setMoveable(boolean moveable)
	{
		this.moveable = moveable;
	}

	public void startFire()
	{
		this.isTryingToFire = true;
	}

	public void stopFire()
	{
		this.isTryingToFire = false;
	}

	public boolean isTryToFire()
	{
		return this.isTryingToFire;
	}

	public Rectangle getCannon()
	{
		return this.cannon;
	}
}